#include "matrix.h"
#include "stm32f4xx.h"
#include "memory.h"
#include "interrupt.h"
#include "thread.h"
#include "mxsetup.h"

/* export symbol of memory layout from .lds */
#ifdef MXSETUP_LOADREGION_IS_FLASH
extern void Load$$RW_IRAM1$$RW$$Base;
extern void Load$$RW_IRAM1$$RW$$Limit;
const mx_void_pt __data_start_flash = (mx_void_pt)&Load$$RW_IRAM1$$RW$$Base;
const mx_void_pt __data_end_flash = (mx_void_pt)&Load$$RW_IRAM1$$RW$$Limit;
const mx_void_pt __user_flash_start = __data_end_flash;
const mx_void_pt __user_flash_end = (mx_void_pt)(MXSETUP_LOADREGION_ADDR + MXSETUP_LOADREGION_SIZE);
const mx_void_pt __heap_end = (mx_void_pt)(MXSETUP_EXECREGION_ADDR + MXSETUP_EXECREGION_SIZE);
#else
const mx_void_pt __heap_end = (mx_void_pt)(MXSETUP_LOADREGION_ADDR + MXSETUP_LOADREGION_SIZE);
#endif
extern void Image$$RW_IRAM1$$RW$$Base;
extern void Image$$RW_IRAM1$$RW$$Limit;
extern void Image$$RW_IRAM1$$ZI$$Base;
extern void Image$$RW_IRAM1$$ZI$$Limit;
const mx_void_pt __data_start = (mx_void_pt)&Image$$RW_IRAM1$$RW$$Base;
const mx_void_pt __data_end = (mx_void_pt)&Image$$RW_IRAM1$$RW$$Limit;
const mx_void_pt __bss_start = (mx_void_pt)&Image$$RW_IRAM1$$ZI$$Base;
const mx_void_pt __bss_end = (mx_void_pt)&Image$$RW_IRAM1$$ZI$$Limit;
const mx_void_pt __stack_limit = __bss_end; // __stack_base defined in vector.S (use it need &__stack_base)
const mx_void_pt __heap_start = __bss_end;

/* board level initialization
   can't called System_Init() function because it will modify the SCB->BTOR */
static void board_init ()
{
    /* 0 bit for pre-emption priority, 4 bits for subpriority
       that can disable interrupt nesting */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* PendSV NVIC configuratioin */
    NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_PriorityGroup_0, 0, 0));    // the priority of PendSV must be highest
    /* initialize memory */
    mx_memory_register("IRAM1", __heap_start, __heap_end - __heap_start);
}
MX_BOARDINIT_EXPORT(board_init, 0);
